package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.entity.WhStockOutGoods;
import com.dingreading.cloud.admin.entity.table.WhStockOutGoodsTableDef;
import com.dingreading.cloud.admin.mapper.WhStockOutGoodsMapper;
import com.dingreading.cloud.admin.service.WhStockOutGoodsService;
import com.dingreading.cloud.common.util.NepUtil;
import com.dingreading.cloud.common.util.PageUtil;
import com.dingreading.cloud.common.util.QueryFiledUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class WhStockOutGoodsServiceImpl extends BaseServiceImpl<WhStockOutGoodsMapper, WhStockOutGoods, WhStockOutGoodsTableDef> implements WhStockOutGoodsService {

    @Override
    protected WhStockOutGoodsTableDef getTable() {
        return WhStockOutGoodsTableDef.whStockOutGoods;
    }

    @Resource
    protected WhStockOutGoodsMapper stockOutGoodsMapper;

    @Override
    public Page<WhStockOutGoods> pageList(PageUtil pageUtil, String keyword, Integer status, Integer realStatus, Integer stockOutMethod, String beginDate, String endDate) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(keyword)) {
            condition.and(table.orderCode.like(keyword)
                    .or(table.outCode.like(keyword))
                    .or(table.goodsTypeName.like(keyword))
                    .or(table.goodsName.like(keyword))
            );
        }

        if (null != status)
            condition.and(table.status.eq(status));
        if (null != realStatus)
            condition.and(table.realStatus.eq(realStatus));
        if (null != stockOutMethod)
            condition.and(table.stockOutMethod.eq(stockOutMethod));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.addTime.between(QueryFiledUtil.appendMin00(beginDate), QueryFiledUtil.appendMin24(endDate)));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.id.desc());

        return getMapper().paginate(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper);
    }

    @Override
    public List<WhStockOutGoods> getByOrderCodeV2(String orderCode, Integer stockOutMethod, List<Integer> status) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.orderCode.eq(orderCode));
        if (CollectionUtils.isNotEmpty(status)) {
            condition.and(table.status.in(status));
        }
        if (null != stockOutMethod)
            condition.and(table.stockOutMethod.eq(stockOutMethod));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<WhStockOutGoods> getByOutCode(String outCode) {
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.outCode.eq(outCode))
                .orderBy(table.freeDeliveryStatus.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public boolean cancel(String outCode, String staffUid, String staffName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.outCode.eq(outCode))
                .and(table.status.eq(2));

        return UpdateChain.of(WhStockOutGoods.class)
                .set(table.status, 0)
                .set(table.statusName, "已取消")
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(condition)
                .update();
    }

    @Override
    public int dropByOutCode(String outCode) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.outCode.eq(outCode))
                .and(table.status.eq(2));
        return getMapper().deleteByCondition(condition);
    }

    @Override
    public int dropByOutCodeAndId(String outCode, Long id) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.outCode.eq(outCode))
                .and(table.id.eq(id))
                .and(table.status.eq(2));
        return getMapper().deleteByCondition(condition);
    }

    @Override
    public List<WhStockOutGoods> getOutGoodsListV2(List<String> orderCode, Integer stockOutMethod) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.orderCode.in(orderCode));
        if (null != stockOutMethod)
            condition.and(table.stockOutMethod.eq(stockOutMethod));
        return getMapper().selectListByCondition(condition);
    }


    @Override
    public WhStockOutGoods getByOutCodeAndId(String outCode, Long id) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.outCode.eq(outCode))
                .and(table.id.eq(id));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public boolean setRefund(String outCode, Long id, String staffUid, String staffName, String refundRemark, Date time) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.id.eq(id))
                .and(table.outCode.eq(outCode))
                .and(table.status.eq(1));

        return UpdateChain.of(WhStockOutGoods.class)
                .set(table.status, -1)
                .set(table.statusName, "出库已退")
                .set(table.refundUid, staffUid)
                .set(table.refundName, staffName)
                .set(table.refundRemark, refundRemark)
                .set(table.refundTime, time)
                .where(condition)
                .update();
    }

    @Override
    public long getDuplicateShopCartId(String outCode, Long shopCartId) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.outCode.eq(outCode))
                .and(table.shopCartId.eq(shopCartId));

        return getMapper().selectCountByCondition(condition);
    }

    @Override
    public int dropSaveOutGoods(String orderCode) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.orderCode.in(orderCode))
                .and(table.status.eq(2));

        return getMapper().deleteByCondition(condition);
    }

    @Override
    public Map<Long, Integer> getSendNum(List<Long> goodsTypeIds) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.status.eq(1))
                .and(table.goodsTypeId.in(goodsTypeIds));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(QueryMethods.sum(table.num).as("cnt"), table.goodsTypeId)
                .from(table)
                .where(condition)
                .groupBy(table.goodsTypeId);

        List<Row> list = getMapper().selectRowsByQuery(wrapper);

        Map<Long, Integer> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Row row : list) {
                Long goodsTypeId = row.getLong("goods_type_id");
                Integer cnt = row.getInt("cnt");
                map.put(goodsTypeId, NepUtil.nullToZero(cnt));
            }
        }
        return map;
    }

    @Override
    public Map<Long, List<WhStockOutGoods>> listByGoodsTypeIdAndAddTimeBetween(List<Long> goodsTypeIds, String beginDate, String endDate) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.status.eq(1))
                .and(table.goodsTypeId.in(goodsTypeIds));

        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate))
            condition.and(table.addTime.between(QueryFiledUtil.appendMin00(beginDate), QueryFiledUtil.appendMin24(endDate)));

        List<WhStockOutGoods> list = getMapper().selectListByCondition(condition);
        Map<Long, List<WhStockOutGoods>> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(list)) {
            map = list.stream().collect(Collectors.groupingBy(WhStockOutGoods::getGoodsTypeId));
        }
        return map;
    }

    @Override
    public List<WhStockOutGoods> listByOrderCodesAndStatus(List<String> codeList, Integer status) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.orderCode.in(codeList));
        if (null != status)
            condition.and(table.status.eq(status));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public Map<Long, Integer> getShopCartOutNum(String orderCode, Integer status, Integer stockOutMethod) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.orderCode.eq(orderCode));
        if (null != status)
            condition.and(table.status.eq(status));
        if (null != stockOutMethod)
            condition.and(table.stockOutMethod.eq(stockOutMethod));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.shopCartId, QueryMethods.sum(table.num).as("num"))
                .from(table)
                .where(condition)
                .groupBy(table.shopCartId);

        List<Row> rows = getMapper().selectRowsByQuery(wrapper);

        Map<Long, Integer> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(rows)) {
            for (Row row : rows) {
                Long goodsTypeId = row.getLong("shop_cart_id");
                Integer integer = row.getInt("num");
                if (goodsTypeId != null)
                    map.put(goodsTypeId, NepUtil.nullToZero(integer));
            }
        }
        return map;
    }

    @Override
    public List<WhStockOutGoods> listByOutCodes(List<String> outCodes) {
        return getMapper().selectListByCondition(table.outCode.in(outCodes));
    }

    @Override
    public Map<Long, Double> lastWetAvgPriceByGoodsTypeIds(String beginDate, String endDate, List<Long> goodsTypeIds) {
        List<WhStockOutGoods> list = stockOutGoodsMapper.lastWetAvgPriceByGoodsTypeIds(beginDate, endDate, goodsTypeIds);

        // 结果默认值设置0
        Map<Long, Double> map = new HashMap<>();
        for (Long goodsTypeId : goodsTypeIds) {
            map.put(goodsTypeId, 0d);
        }

        if (CollectionUtils.isNotEmpty(list))
            map = list.stream().collect(Collectors.toMap(WhStockOutGoods::getGoodsTypeId, WhStockOutGoods::getWetAvgPrice));

        return map;
    }

}
